#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <LittleFS.h>  // 添加LittleFS库
#include <WiFiManager.h> // WiFi配置管理库
#include "epd.h"        // e-Paper driver

// 定义配置按钮引脚 (GPIO0 是 flash 按钮)
#define CONFIG_PIN 0

// 创建 WebServer 实例
ESP8266WebServer server(80);
// 创建 WiFiManager 实例
WiFiManager wifiManager;
IPAddress myIP;       // IP address in your local wifi net


void handleHtml(String filename)
{
  Serial.println("/index.html");
  if (LittleFS.exists(filename)) {
    File file = LittleFS.open(filename, "r");
    server.streamFile(file, "text/html");
    file.close();
    return;
  }

  server.send(200, "text/html", "file not found");
}

void handleJs(String filename)
{
  if (LittleFS.exists(filename)) {
    File file = LittleFS.open(filename, "r");
    server.streamFile(file, "application/javascript");
    file.close();
    return;
  }

  server.send(200, "text/html", "file not found");
}

void handleCss(String filename)
{
  if (LittleFS.exists(filename)) {
    File file = LittleFS.open(filename, "r");
    server.streamFile(file, "text/css");
    file.close();
    return;
  }

  server.send(200, "text/html", "file not found");
}

void handleSvg(String filename)
{
  if (LittleFS.exists(filename)) {
    File file = LittleFS.open(filename, "r");
    server.streamFile(file, "image/svg+xml");
    file.close();
    return;
  }

  server.send(200, "text/html", "file not found");
}

void setup(void) {

  Serial.begin(115200);
  
  // 初始化LittleFS
  if(!LittleFS.begin()){
    Serial.println("LittleFS挂载失败");
  } else {
    Serial.println("LittleFS挂载成功");
  }
  
  // SPI initialization
  pinMode(CS_PIN  , OUTPUT);
  pinMode(RST_PIN , OUTPUT);
  pinMode(DC_PIN  , OUTPUT);
  pinMode(BUSY_PIN,  INPUT);
  SPI.begin();
  
  // 配置 WiFiManager
  pinMode(CONFIG_PIN, INPUT_PULLUP); // 设置配置按钮为输入上拉模式
  
  // 设置配置门户超时时间（秒）
  wifiManager.setConfigPortalTimeout(180);
  
  // 设置AP模式的名称和密码
  // 如果无法连接到已保存的WiFi，将创建一个名为"WaterScreen-AP"的接入点
  Serial.println("正在连接WiFi...");
  
  // 自动连接WiFi，如果不成功，则启动配置门户
  if(!wifiManager.autoConnect("WaterScreen-AP")) {
    Serial.println("连接失败并超时");
    // 重置并重试
    ESP.restart();
  }
  
  Serial.print("\r\nIP address: ");
  Serial.println(myIP = WiFi.localIP());

  if (MDNS.begin("esp8266")) {
    Serial.println("MDNS responder started");
  }


  // 注册自定义路由处理函数
  server.on("/", []() { handleHtml("/index.html"); });
  server.on("/index.js", []() { handleJs("/index.js"); });
  server.on("/style.css", []() { handleCss("/style.css"); });
  server.on("/utils.js", []() { handleJs("/utils.js"); });
  server.on("/vendor.js", []() { handleJs("/vendor.js"); });
  server.on("/vite.svg", []() { handleSvg("/vite.svg"); });

  server.on("/LOAD", EPD_Load);
  server.on("/EPD", EPD_Init);
  server.on("/NEXT", EPD_Next);
  server.on("/SHOW", EPD_Show);
  
  // 添加处理静态文件的路由
  server.onNotFound([]() {
    if (!handleFileRead(server.uri())) {
      handleNotFound();
    }
  });

  // 启动 WebServer
  server.begin();
  Serial.println("HTTP server started");
}

// 处理文件读取的函数
bool handleFileRead(String path) {
  Serial.println("handleFileRead: " + path);
  if (path.endsWith("/")) path += "index.html";
  String contentType = getContentType(path);
  if (LittleFS.exists(path)) {
    File file = LittleFS.open(path, "r");
    server.streamFile(file, contentType);
    file.close();
    return true;
  }
  return false;
}

// 获取内容类型
String getContentType(String filename) {
  if (filename.endsWith(".html")) return "text/html";
  else if (filename.endsWith(".css")) return "text/css";
  else if (filename.endsWith(".js")) return "application/javascript";
  else if (filename.endsWith(".png")) return "image/png";
  else if (filename.endsWith(".jpg")) return "image/jpeg";
  else if (filename.endsWith(".ico")) return "image/x-icon";
  else if (filename.endsWith(".svg")) return "image/svg+xml";
  return "text/plain";
}

void loop(void) {
  // 检查是否按下配置按钮（低电平触发）
  if (digitalRead(CONFIG_PIN) == LOW) {
    // 按钮按下，等待确认（防抖）
    delay(50);
    if (digitalRead(CONFIG_PIN) == LOW) {
      Serial.println("配置按钮被按下，启动配置门户...");
      // 启动配置门户，阻塞模式
      wifiManager.startConfigPortal("WaterScreen-AP");
      Serial.println("连接到新网络，重启...");
      ESP.restart();
    }
  }
  
  server.handleClient(); // 处理 WebServer 请求
}

void EPD_Init()
{
  EPD_dispIndex = ((int)server.arg(0)[0] - 'a') +  (((int)server.arg(0)[1] - 'a') << 4);
  // Print log message: initialization of e-Paper (e-Paper's type)
  Serial.printf("EPD %s\r\n", EPD_dispMass[EPD_dispIndex].title);

  // Initialization
  EPD_dispInit();
  server.send(200, "text/plain", "Init ok\r\n");
}

void EPD_Load()
{
  //server.arg(0) = data+data.length+'LOAD'
  String p = server.arg(0);
  if (p.endsWith("LOAD")) {
    int index = p.length() - 8;
    int L = ((int)p[index] - 'a') + (((int)p[index + 1] - 'a') << 4) + (((int)p[index + 2] - 'a') << 8) + (((int)p[index + 3] - 'a') << 12);
    if (L == (p.length() - 8)) {
      Serial.println("LOAD");
      // if there is loading function for current channel (black or red)
      // Load data into the e-Paper
      if (EPD_dispLoad != 0) EPD_dispLoad();
    }
  }
  server.send(200, "text/plain", "Load ok\r\n");
}

void EPD_Next()
{
  Serial.println("NEXT");

  // Instruction code for for writting data into
  // e-Paper's memory
  int code = EPD_dispMass[EPD_dispIndex].next;

  // If the instruction code isn't '-1', then...
  if (code != -1)
  {
    // Do the selection of the next data channel
    EPD_SendCommand(code);
    delay(2);
  }
  // Setup the function for loading choosen channel's data
  EPD_dispLoad = EPD_dispMass[EPD_dispIndex].chRd;

  server.send(200, "text/plain", "Next ok\r\n");
}

void EPD_Show()
{
  Serial.println("\r\nSHOW\r\n");
  // Show results and Sleep
  EPD_dispMass[EPD_dispIndex].show();
  server.send(200, "text/plain", "Show ok\r\n");
}

void handleNotFound() {
  String message = "File Not Found\n\n";
  message += "URI: ";
  message += server.uri();
  message += "\nMethod: ";
  message += (server.method() == HTTP_GET) ? "GET" : "POST";
  message += "\nArguments: ";
  message += server.args();
  message += "\n";
  for (uint8_t i = 0; i < server.args(); i++) {
    message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
  }
  server.send(200, "text/plain", message);
  Serial.print("Unknown URI: ");
  Serial.println(server.uri());
}
